﻿using System.Configuration;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.WebPages;

namespace CatagorizrMvc4 {
    public class Detector {

        public bool TabletAsDesktop { get; set; }
        public bool TvAsDesktop { get; set; }
        public string SessionVariable{get; set;}
        public DeviceType Device { get; set; }

        public enum DeviceType{
            Mobile,
            Tablet,
            Tv,
            Desktop
        }

        public Detector() {
            TabletAsDesktop = bool.Parse(ConfigurationManager.AppSettings["TabletAsDesktop"]);
            TvAsDesktop = bool.Parse(ConfigurationManager.AppSettings["TvAsDesktop"]);
            SessionVariable = ConfigurationManager.AppSettings["SessionVariable"];
        }

        public virtual void Detect(HttpContextBase context) {
            if (!CheckSession(context)) {
                string useragent = context.GetOverriddenUserAgent();

                // Check if user agent is a smart TV
                if (Regex.IsMatch(useragent, "GoogleTV|SmartTV|Internet.TV|NetCast|NETTV|AppleTV|boxee|Kylo|Roku|DLNADOC|CE\\-HTML", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tv;
                } // Check if user agent is a TV Based Gaming Console
                else if (Regex.IsMatch(useragent, "Xbox|PLAYSTATION.3|Wii", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tv;
                } // Check if user agent is a Tablet
                else if (Regex.IsMatch(useragent, "iP(a|ro)d", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) || Regex.IsMatch(useragent, "tablet", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && !Regex.IsMatch(useragent, "RX-34", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) || Regex.IsMatch(useragent, "FOLIO", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tablet;
                }// Check if user agent is an Android Tablet
                else if (Regex.IsMatch(useragent, "Linux", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "Android", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && !Regex.IsMatch(useragent, "Fennec|mobi|HTC.Magic|HTCX06HT|Nexus.One|SC-02B|fone.945", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tablet;
                }// Check if user agent is a Kindle or Kindle Fire
                else if (Regex.IsMatch(useragent, "Kindle", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) || Regex.IsMatch(useragent, "Mac.OS", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "Silk", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tablet;
                }// Check if user agent is a pre Android 3.0 Tablet
                else if (Regex.IsMatch(useragent, "GT-P10|SC-01C|SHW-M180S|SGH-T849|SCH-I800|SHW-M180L|SPH-P100|SGH-I987|zt180|HTC(.Flyer|Flyer)|Sprint.ATP51|ViewPad7|pandigital(sprnova|nova)|Ideos.S7|Dell.Streak.7|Advent.Vega|A101IT|A70BHT|MID7015|Next2|nook", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) || Regex.IsMatch(useragent, "MB511", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "RUTEM", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tablet;
                }// Check if user agent is unique Mobile User Agent
                else if (Regex.IsMatch(useragent, "BOLT|Fennec|Iris|Maemo|Minimo|Mobi|mowser|NetFront|Novarra|Prism|RX-34|Skyfire|Tear|XV6875|XV6975|Google.Wireless.Transcoder", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Mobile;
                }// Check if user agent is an odd Opera User Agent
                else if (Regex.IsMatch(useragent, "Opera", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "Windows.NT.5", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "HTC|Xda|Mini|Vario|SAMSUNG\\-GT\\-i8000|SAMSUNG\\-SGH\\-i9", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Mobile;
                }// Check if user agent is Windows Desktop
                else if (Regex.IsMatch(useragent, "Windows.(NT|XP|ME|9)", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && !Regex.IsMatch(useragent, "Phone", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) || Regex.IsMatch(useragent, "Win(9|.9|NT)", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Desktop;
                }// Check if agent is Mac Desktop
                else if (Regex.IsMatch(useragent, "Macintosh|PowerPC", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && !Regex.IsMatch(useragent, "Silk", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Desktop;
                }// Check if user agent is a Linux Desktop
                else if (Regex.IsMatch(useragent, "/Linux", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "X11", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Desktop;
                }// Check if user agent is a Solaris, SunOS, BSD Desktop
                else if (Regex.IsMatch(useragent, "Solaris|SunOS|BSD")) {
                    Device = DeviceType.Tv;
                }// Check if user agent is a Desktop BOT/Crawler/Spider
                else if (Regex.IsMatch(useragent, "Bot|Crawler|Spider|Yahoo|ia_archiver|Covario-IDS|findlinks|DataparkSearch|larbin|Mediapartners-Google|NG-Search|Snappy|Teoma|Jeeves|TinEye", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && !Regex.IsMatch(useragent, "Mobile", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Desktop;
                } else {
                    Device = DeviceType.Mobile;
                }

                if (TabletAsDesktop && Device == DeviceType.Tablet)
                    Device = DeviceType.Desktop;
                if (TvAsDesktop && Device == DeviceType.Tv)
                    Device = DeviceType.Desktop;

                context.Session[SessionVariable] = Device;
            } else {
                Device = (DeviceType)context.Session[SessionVariable];
            }
        }

        public virtual void Detect(string useragent) {         
              

                // Check if user agent is a smart TV
                if (Regex.IsMatch(useragent, "GoogleTV|SmartTV|Internet.TV|NetCast|NETTV|AppleTV|boxee|Kylo|Roku|DLNADOC|CE\\-HTML", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tv;
                } // Check if user agent is a TV Based Gaming Console
                else if (Regex.IsMatch(useragent, "Xbox|PLAYSTATION.3|Wii", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tv;
                } // Check if user agent is a Tablet
                else if (Regex.IsMatch(useragent, "iP(a|ro)d", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) || Regex.IsMatch(useragent, "tablet", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && !Regex.IsMatch(useragent, "RX-34", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) || Regex.IsMatch(useragent, "FOLIO", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tablet;
                }// Check if user agent is an Android Tablet
                else if (Regex.IsMatch(useragent, "Linux", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "Android", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && !Regex.IsMatch(useragent, "Fennec|mobi|HTC.Magic|HTCX06HT|Nexus.One|SC-02B|fone.945", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tablet;
                }// Check if user agent is a Kindle or Kindle Fire
                else if (Regex.IsMatch(useragent, "Kindle", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) || Regex.IsMatch(useragent, "Mac.OS", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "Silk", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tablet;
                }// Check if user agent is a pre Android 3.0 Tablet
                else if (Regex.IsMatch(useragent, "GT-P10|SC-01C|SHW-M180S|SGH-T849|SCH-I800|SHW-M180L|SPH-P100|SGH-I987|zt180|HTC(.Flyer|Flyer)|Sprint.ATP51|ViewPad7|pandigital(sprnova|nova)|Ideos.S7|Dell.Streak.7|Advent.Vega|A101IT|A70BHT|MID7015|Next2|nook", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) || Regex.IsMatch(useragent, "MB511", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "RUTEM", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Tablet;
                }// Check if user agent is unique Mobile User Agent
                else if (Regex.IsMatch(useragent, "BOLT|Fennec|Iris|Maemo|Minimo|Mobi|mowser|NetFront|Novarra|Prism|RX-34|Skyfire|Tear|XV6875|XV6975|Google.Wireless.Transcoder", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Mobile;
                }// Check if user agent is an odd Opera User Agent
                else if (Regex.IsMatch(useragent, "Opera", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "Windows.NT.5", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "HTC|Xda|Mini|Vario|SAMSUNG\\-GT\\-i8000|SAMSUNG\\-SGH\\-i9", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Mobile;
                }// Check if user agent is Windows Desktop
                else if (Regex.IsMatch(useragent, "Windows.(NT|XP|ME|9)", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && !Regex.IsMatch(useragent, "Phone", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) || Regex.IsMatch(useragent, "Win(9|.9|NT)", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Desktop;
                }// Check if agent is Mac Desktop
                else if (Regex.IsMatch(useragent, "Macintosh|PowerPC", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && !Regex.IsMatch(useragent, "Silk", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Desktop;
                }// Check if user agent is a Linux Desktop
                else if (Regex.IsMatch(useragent, "/Linux", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && Regex.IsMatch(useragent, "X11", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Desktop;
                }// Check if user agent is a Solaris, SunOS, BSD Desktop
                else if (Regex.IsMatch(useragent, "Solaris|SunOS|BSD")) {
                    Device = DeviceType.Tv;
                }// Check if user agent is a Desktop BOT/Crawler/Spider
                else if (Regex.IsMatch(useragent, "Bot|Crawler|Spider|Yahoo|ia_archiver|Covario-IDS|findlinks|DataparkSearch|larbin|Mediapartners-Google|NG-Search|Snappy|Teoma|Jeeves|TinEye", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) && !Regex.IsMatch(useragent, "Mobile", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase)) {
                    Device = DeviceType.Desktop;
                } else {
                    Device = DeviceType.Mobile;
                }

                if (TabletAsDesktop && Device == DeviceType.Tablet)
                    Device = DeviceType.Desktop;
                if (TvAsDesktop && Device == DeviceType.Tv)
                    Device = DeviceType.Desktop;         
        }

        private bool CheckSession(HttpContextBase context) {
            if (context.Session[SessionVariable] == null)
                return false;
            else
                return true;
        }
    }
}
